<?php

/**
 * 获取未读消息总数
 * @param $userId
 * @return null|string
 */
function getUnreadNotificationsCount($userId) {
    global $uddb;

    $sql = "SELECT count(id) as count FROM `history_user_notification` WHERE `user_id`=:uid and status = 0";
    $count = $uddb->getVar($sql, array(':uid' => $userId));
    return $count;
}
/**
 * 获取消息列表
 * @param array $queryArgs
 * @return array
 */
function getNotiFications($queryArgs) {
    global $uddb, $cmsdb;

    if (empty($queryArgs['page']) || validateUser($queryArgs) !== 1) {
        return array();
    }

    $pageNum = 20;
    $start   = $pageNum * ($queryArgs['page'] - 1);

    //获取该页消息
    $sql = "SELECT * FROM `history_user_notification` WHERE `user_id`=:uid ORDER BY `send_time` DESC LIMIT {$start}, {$pageNum}";
    $all = $uddb->getResults($sql, array(':uid' => $queryArgs['user_id']));

    //获取学生信息
    $studentIds = array();
    $exerciseIds = [];
    foreach ($all as $item) {
        if ($item->type == 2)
            $studentIds[] = $item->sender_id;

        if (!empty($item->primary_exercise_id))
            $exerciseIds[] = $item->primary_exercise_id;
    }
    $students = getStudentInfo($studentIds);

    //获取消息对应的作业类型
    $queryString = implode(',', $exerciseIds);
    $exerciseTypes = (array)$cmsdb->getResults("SELECT `id`, `type_id` FROM `data_primary_exercise` WHERE `id` IN ({$queryString})");
    $typeList = [];
    foreach ($exerciseTypes as $exerciseType) {
        $typeList[$exerciseType->id] = (int)$exerciseType->type_id;
    }

    //构造返回数据
    $list = array();
    foreach ($all as $item) {
        $list[] = array(
            'id'                  => (int)$item->id,
            'exercise_id'         => (int)$item->primary_exercise_id,
            'exercise_type'       => isset($typeList[$item->primary_exercise_id]) ? $typeList[$item->primary_exercise_id] : 0,
            'type'                => (int)$item->type,
            'title'               => (string)$item->title,
            'content'             => (string)$item->content,
            'redirect_url'        => (string)$item->redirect_url,
            'mobile_redirect_url' => (string)$item->mobile_redirect_url,
            'send_time'           => $item->send_time,
            'is_read'             => $item->status == 1,
            'sender'              => $item->type == 2 ? $students[$item->sender_id] : getLectorInfo($item->sender_id)
        );
    }
    return $list;
}

/**
 * 获取学生信息
 *
 * @param array $userIds 用户id
 * @return array
 */
function getStudentInfo($userIds) {
    global $uddb;

    $userIds = implode(',', $userIds);

    $data = $uddb->getResults("SELECT `user_id`, `nickname`, `avatar` FROM `user_social_info` WHERE `user_id` IN ({$userIds})");

    $list = array();
    foreach ($data as $item) {
        //兼容每日一题的头像保存url
        if (!empty($item->avatar) && strpos($item->avatar, 'http://') === false) {
            $item->avatar = 'http://edu.appublisher.com/user-images/avatar/'.$item->avatar;
        }
        $list[$item->user_id] = array(
            'id'     => intval($item->user_id),
            'avatar' => (string)$item->avatar,
            'name'   => $item->nickname
        );
    }

    return $list;
}

/**
 * 获取教师信息
 *
 * @param int $letorId 教师id
 * @return array
 */
function getLectorInfo($letorId) {
    global $cmsdb;

    $cacheKey = 'vip:func:getLectorInfo:'.$letorId;
    if (($lectorInfo = cacheGet($cacheKey)) == null) {
        $res = $cmsdb->getRow('SELECT `name`, `avatar` FROM `data_teacher` WHERE `id`=:id', array(':id' => $letorId));
        $lectorInfo = array(
            'id'     => (int)$letorId,
            'name'   => $res->name,
            'avatar' => (string)$res->avatar
        );

        cacheAdd($cacheKey, $lectorInfo, 24*60*60);
    }

    return $lectorInfo;
}

/**
 * 获取公告列表
 *
 * @param int $userId 用户id
 * @param int $announceId 单个公告id
 * @return array
 */
function getAnnounceList($userId, $announceId = 0) {
    global $uddb, $cmsdb;

    if ($announceId == 0) {
        //获取所有公告
        $now = date('Y-m-d H:i:s');
        $all = (array)$cmsdb->getResults('SELECT * FROM `data_primary_announce` WHERE `publish_date`<=:date ORDER BY `publish_date` DESC', [':date' => $now]);
    } else {
        $all = (array)$cmsdb->getResults('SELECT * FROM `data_primary_announce` WHERE `id`=:id', [':id' => $announceId]);
    }

    //获取该用户已读公告
    $readList = (array)$uddb->getCol('SELECT `announce_id` FROM `history_user_announce` WHERE `user_id`=:uid', [':uid' => $userId]);

    $results = [];
    foreach ($all as $item) {
        $data = [
            'id'           => (int)$item->id,
            'title'        => $item->title,
            'content'      => $item->content,
            'publish_date' => $item->publish_date,
            'is_read'      => false
        ];

        //如果该公告已读
        if (in_array($item->id, $readList, true)) {
            $data['is_read'] = true;
        }

        $results[] = $data;
    }

    return $results;
}

/**
 * 获取作业列表
 * @param $queryArgs
 * @return array
 */
function getFilteredExercise($queryArgs) {

    global $cmsdb, $uddb;

    //参数校验
    if (validateUser($queryArgs) !== 1 || !isset($queryArgs['status_id']) || !isset($queryArgs['category_id'])
        || !isset($queryArgs['type_id'])) {
        return array();
    }

    //过滤字段
    $userId     = intval($queryArgs['user_id']);        //用户
    $status     = intval($queryArgs['status_id']);      //状态
    $category   = intval($queryArgs['category_id']);    //科目
    $type       = intval($queryArgs['type_id']);        //类型

    //获取用户已购课程,字符串形式
    $courseStr = getUserPurchasedCourses($userId);


    /**======================================================
    | 获取与用户产生关联的作业,指定用户的作业或已提交、完成的作业
    ------------------------------------------------------*/
    $sql = "SELECT upe.id, upe.exercise_id, pe.assign_type, upe.start_time, upe.end_time, upe.status
                FROM userdata.`history_user_primary_exercise` AS upe INNER JOIN educms.`data_primary_exercise` AS pe
                ON upe.user_id={$userId} AND upe.exercise_id=pe.id";
    $userExerciseData = (array)$cmsdb->getResults($sql);

    $userExercises = array();       //所有作业
    $noCourseExercises = array(); //指定用户的作业
    foreach ($userExerciseData as $e) {
        if ($e->assign_type == 1) {
            $noCourseExercises[] = $e->exercise_id;
        }

        $userExercises[$e->exercise_id] = $e;
    }

    //构造指定用户作业的IN查询字符串
    if (empty($noCourseExercises)) {
        $noCourseExerciseStr = '0';
    } else {
        $noCourseExerciseStr = implode(',', $noCourseExercises);
    }


    /**======================================================
    | 获取作业信息
    ------------------------------------------------------*/
    $sql = "SELECT * FROM `data_primary_exercise` WHERE 1";

    //类型过滤
    if ($type != -1) {
        $sql .= " AND `type_id`={$type}";
    } elseif ($category != -1) { //科目过滤
        $typeStr = getCategoryTypeStr($category);
        $sql .= " AND `type_id` IN ({$typeStr})";
    }

    //指定课程课堂或指定用户过滤
    $sql .= " AND (`assign_type`=0 AND `course_id` IN ({$courseStr}) OR (`assign_type`=1 AND `id` IN ({$noCourseExerciseStr})))";

    //时间过滤
    $now = date('Y-m-d H:i:s');
    $sql .= " AND `start_time`<'{$now}' AND `status`=1";

    //查询结果
    $list = (array)$cmsdb->getResults($sql);


    /**======================================================
    | 按照作业状态分组
    ------------------------------------------------------*/
    $done           = array(); //已完成, status_id=1
    $undone         = array(); //未完成(没有做的作业), status_id=0
    $outdated       = array(); //过期, status_id=6
    $rejected       = array(); //被驳回, status_id=4
    $submitted      = array(); //已提交(需要教师批改的作业才有的状态), status_id=3
    $outdateDone    = array(); //过期完成, status_id=5

    $now = date('Y-m-d H:i:s');
    foreach ($list as $item) {

        //格式化数据
        $structured = array(
            'exercise_id'   => (int)$item->id,
            'exercise_type' => (int)$item->type_id,
            'teacher_name'  => getLectorName($item->creator),
            'name'          =>  $item->name,
            'course_name'   => getCourseName($item->course_id),
            'class_name'    => getClassName($item->class_id)
        );

        if (!isset($userExercises[$item->id])) {  //还未产生用户-作业关系, 状态有: 未完成、已过期

            //排序key
            $sortKey = genSortKey($item->end_time, $item->id);

            //以公共作业来设置作业时间
            $structured['start_time']   = $item->start_time;
            $structured['end_time']     = $item->end_time;

            if ($item->end_time > $now) { //未完成
                $structured['status']      = 0;
                $structured['status_text'] = VipUtils::getStatusText(0);

                //防止相同结束时间的作业被覆盖
                $undone[$sortKey]  = $structured;

            } else {  //已过期
                $structured['status']      = 6;
                $structured['status_text'] = VipUtils::getStatusText(6);

                //防止相同结束时间的作业被覆盖
                $outdated[$sortKey] = $structured;
            }
            continue;
        }

        //已产生用户-作业关系, 状态有: 已完成、被驳回、已提交、过期完成、未完成、已过期
        $userExercise = $userExercises[$item->id];
        $sortKey      = genSortKey($userExercise->end_time, $item->id);


        //以用户作业记录来设置时间、状态
        $structured['start_time']   = $userExercises[$item->id]->start_time;
        $structured['end_time']     = $userExercises[$item->id]->end_time;
        $structured['status']       = (int)$userExercises[$item->id]->status;
        $structured['status_text']  = VipUtils::getStatusText($structured['status']);

        switch($userExercise->status) {
            case 0: //未完成,指定到人
                if ($userExercise->end_time > $now) { //未过期
                    $undone[$sortKey]  = $structured;
                } else { //过期了
                    $structured['status']      = 6; //更新状态为过期
                    $structured['status_text'] = VipUtils::getStatusText(6);
                    $outdated[$sortKey] = $structured;
                    //更新状态为过期
                    $uddb->update('history_user_primary_exercise', array('status' => 6), array('id' => $userExercise->id));
                }
                break;
            case 6: //已过期
                $outdated[$sortKey]    = $structured;
                break;
            case 1: //已完成
                $done[$sortKey]        = $structured;
                break;
            case 3: //已提交
                $submitted[$sortKey]   = $structured;
                break;
            case 4: //已驳回
                if ($userExercise->end_time > $now) { //未过期
                    $undone[$sortKey]  = $structured;
                } else { //过期了
                    $structured['status']      = 6; //更新状态为过期
                    $structured['status_text'] = VipUtils::getStatusText(6);
                    $outdated[$sortKey] = $structured;
                    //更新状态为过期
                    $uddb->update('history_user_primary_exercise', array('status' => 6), array('id' => $userExercise->id));
                }
                break;
            case 5: //过期完成
                $outdateDone[$sortKey] = $structured;
                break;
            default:
        }
    }


    /**======================================================
    | 按照作业状态过滤及排序
    ------------------------------------------------------*/
    $filteredExercises = array();

    if ($status == -1 || $status == 4) { //被驳回优先级最高
        ksort($rejected);
        $filteredExercises = array_merge($filteredExercises, array_values($rejected));
    }

    if ($status == -1 || $status == 0) { //未完成
        ksort($undone);
        $filteredExercises = array_merge($filteredExercises, array_values($undone));
    }

    if ($status == -1 || $status == 6) { //已过期
        ksort($outdated);
        $filteredExercises = array_merge($filteredExercises, array_values($outdated));
    }

    if ($status == -1 || $status == 3) { //已提交
        ksort($submitted);
        $filteredExercises = array_merge($filteredExercises, array_values($submitted));
    }

    if ($status == -1 || $status == 5) { //过期完成
        ksort($outdateDone);
        $filteredExercises = array_merge($filteredExercises, array_values($outdateDone));
    }

    if ($status == -1 || $status == 1) { //已完成
        ksort($done);
        $filteredExercises = array_merge($filteredExercises, array_values($done));
    }

    if ( $status == 9) { //0 未完成  4 被驳回     6过期
        //被驳回优先级最高
        ksort($rejected);
        $filteredExercises = array_merge($filteredExercises, array_values($rejected));
        //未完成
        ksort($undone);
        $filteredExercises = array_merge($filteredExercises, array_values($undone));
    }

    return $filteredExercises;
}

/**
 * 获取用户已购课程
 *
 * @param int $userId 用户id
 * @return bool|string
 */
function getUserPurchasedCourses($userId) {
    global $cmsdb;

    $sql = 'SELECT `product_id` FROM `relation_user_product` WHERE `user_id`=:uid AND `product_type`="zhiboke"';
    $courses = (array)$cmsdb->getCol($sql, array(':uid' => $userId));

    return empty($courses) ? '0' : implode(',', $courses);
}

/**
 * 获取作业课程名
 *
 * @param int $courseId 课程id
 * @return string
 */
function getCourseName($courseId) {
    global $cmsdb;

    if (empty($courseId)) {
        return '';
    }

    $cacheKey = 'vip:func:getCourseName';
    if (($courses = cacheGet($cacheKey)) == null || !isset($courses[$courseId])) {
        if (!$courses) {
            $courses = array();
        }

        $courses[$courseId] = (string)$cmsdb->getVar('SELECT `course_name` FROM `data_live_course` WHERE `id`=:cid', array(':cid' => $courseId));
        cacheSet($cacheKey, $courses, 24*60*60);
    }

    return $courses[$courseId];
}
/**
 * 获取作业课堂名
 *
 * @param int $classId 课堂id
 * @return string
 */
function getClassName($classId) {
    global $cmsdb;

    if (empty($classId)) {
        return '';
    }

    $cacheKey = 'vip:func:getClassName';
    if (($classes = cacheGet($cacheKey)) == null || !isset($classes[$classId])) {
        if (!$classes) {
            $classes = array();
        }

        $classes[$classId] = (string)$cmsdb->getVar('SELECT `class_name` FROM `data_live_class` WHERE `id`=:cid', array(':cid' => $classId));
        cacheSet($cacheKey, $classes, 24*60*60);
    }

    return $classes[$classId];
}
/**
 * 获取作业老师名
 *
 * @param int $lectorId 教师id
 * @return string
 */
function getLectorName($lectorId) {
    global $cmsdb;

    if (empty($lectorId)) {
        return '';
    }

    $cacheKey = 'vip:func:getLectorName';
    if (($lectors = cacheGet($cacheKey)) == null || !isset($lectors[$lectorId])) {
        if (!$lectors) {
            $lectors = array();
        }

        $lectors[$lectorId] = (string)$cmsdb->getVar('SELECT `name` FROM `data_teacher` WHERE `id`=:tid', array(':tid' => $lectorId));
        cacheSet($cacheKey, $lectors, 24*60*60);
    }

    return $lectors[$lectorId];
}
/**
 * 创建排序key
 *
 * @param string $date 作业结束日期
 * @param int $id 作业id
 * @return string
 */
function genSortKey($date, $id) {
    return $date . dechex($id);
}

/**
 * 根据科目获取作业类型
 *
 * @param int $categoryId 科目id
 * @return string
 */
function getCategoryTypeStr($categoryId) {
    global $cmsdb;

    $cacheKey = 'vip:func:getCategoryType:'.$categoryId;
    if (($types = cacheGet($cacheKey)) == null) {
        $types = (array)$cmsdb->getCol('SELECT `id` FROM `conf_primary_exercise_type` WHERE `note_category_id`=:cid', array(':cid' => $categoryId));

        cacheAdd($cacheKey, $types, 24*60*60);
    }

    return implode(',', $types);
}

/**
 * 获取课程列表
 * @param $user_id
 * @param $type
 * @return array()
 */
function getCourseListByUserId($userId, $type = '') {
    global $cmsdb;

    $type_str = !empty($type)? ' and b.type_id = '.intval($type) : '' ;
    $sql = "select a.user_id, a.product_id, a.product_type, b.id as course_id, b.course_name from relation_user_product as a LEFT JOIN data_live_course as b on a.product_id = b.id
          WHERE a.product_type = 'zhiboke' ".$type_str." and a.user_id = :user_id";
    $result = $cmsdb->getResults($sql, array(':user_id'=>$userId));

    $newArray = [];
    if (!empty($result)) {
        foreach ($result as $key => $item) {
            $data = [
                'user_id'       => $item->user_id,
                'product_id'    => $item->product_id,
                'product_type'  => $item->product_type,
                'course_id'     => $item->course_id,
                'course_name'   => $item->course_name,
            ];
            $newArray[] = $data;
        }
    }
    return $newArray;
}

/**
 * 根据课程ID查询未结束的课堂
 *
 * @param $courseId
 * @return array|mixed
 */
function getClassRoomListByCourseId($courseId) {
    global $cmsdb;

    $sql = "select a.course_id, a.class_id, b.class_name, b.lector_id, b.start_time, b.end_time from relationship_live_class_and_course as a LEFT JOIN data_live_class as b on a.class_id=b.id
where   b.end_time > :nowTime and b.end_time < :nowDay  and a.course_id = :course_id ";
    $result = $cmsdb->getResults($sql,
        array(
            ':course_id'    => $courseId,
            ':nowTime'      => date('Y-m-d H:i:s'),
            ':nowDay'       => date('Y-m-d 23:59:59')
        ));

    $newArray = [];
    if (!empty($result)) {
        foreach ($result as $key => $item) {
            $teacherInfo = getLectorInfo($item->lector_id);
            $data = [
                'course_id'     => $item->course_id,
                'course_name'   => getCourseName($item->course_id),
                'class_id'      => $item->class_id,
                'class_name'    => $item->class_name,
                'start_time'    => $item->start_time,
                'end_time'      => $item->end_time,
                'teacher_id'    => $teacherInfo['id'],
                'teacher_name'  => $teacherInfo['name'],
                'avatar'        => $teacherInfo['avatar']
            ];
            $newArray[] = $data;
        }

        //按开始时间排序
        if (!empty($newArray)) {
            foreach ($newArray as $key=>$value){
                $times[$key] = strtotime($value['start_time']);
            }
            array_multisort($times,SORT_ASC,$newArray);
        }
    }
    return $newArray;
}


/**
 * 获取做题统计信息--全站最高     可考虑加cache 有效时间15~60秒
 *
 * @param $fieldName  做题总数\分数\正确率\昨日做题总数
 * @return null|string
 */
function getHighestByFieldName($fieldName) {
    global  $cmsdb;

    $number = $cmsdb->getVar("select max({$fieldName}) as c from qb_user_data");

    return $number;
}


/**
 * 根据items里的字段--获取全站最高的信息
 *
 * @param $items
 * @return mixed
 */
function getHighestByItems($items) {

    foreach ($items as $k => $v) {

        $items[$k] = getHighestByFieldName($k);
    }

    return $items;
}


/**
 * 处理无效的互评作业
 *
 * @param $userId
 * @return bool|void
 */
function resetHuping($userId) {
    global $cmsdb, $uddb;

    $nowTime = date('Y-m-d H:i:s');
    $sql = 'select id,constraint_ids from data_primary_exercise where type_id=9 and start_time <= :startTime and end_time >= :endTime';
    $dataExercise = (array)$cmsdb->getResults($sql,
        [
            ':startTime'    => $nowTime,
            ':endTime'      => $nowTime,
        ]);

    //作业ID排列组合
    $data = [];
    foreach ($dataExercise as $k => $v) {
        $data[$v->constraint_ids][] = $v->id;
    }

    if (!empty($data)) {

        foreach ($data as $key => $item) {
            //提交人数
            $sql = 'select count(id) as count from history_user_primary_exercise where exercise_id = :eId and status = 1';
            $count = $uddb->getVar($sql,[':eId' => $key]);

            if ($count <= 2) {
                //删除当前用户无效的点评作业
                for ($i = count((array)$item)-1;$i >= 0;$i--) {

                    $uddb->delete('history_user_primary_exercise',['exercise_id' => $item[$i],'user_id' => $userId]);

                    if($count == 2 && $i == 1){
                        break;
                    }
                }
            }
        }
    }
    return true;
}

/**
 *----------------------------------------------
 */

/**
 * 获取用户信息
 *
 * @param int $userId 用户id
 * @return null|Object
 */
function getUserData($userId) {
    global $cmsdb;

    $cacheKey = 'qb_userData:'.$userId;

    if (($value = cacheGet($cacheKey)) != null) {
        return $value;
    } else {
        $value = $cmsdb->getRow('SELECT * FROM `qb_user_data` WHERE `user_id`=:user_id', array(':user_id' => $userId));
        if (!empty($value)) {
            cacheAdd($cacheKey, $value, 24*60*60); //24小时缓存时间

            return $value;
        }
    }
    return null;
}

/**
 * 获取qb_user_data 的全站最高纪录-估分\总题数\正确率
 *
 * from  quizbank/includes/utils.php getScoreRank 已修改
 * @param $examDetailId
 * @param $fieldName
 * @param $userValue
 * @return float
 */
function getUserDataRank($examDetailId, $fieldName,  $userValue, $userId='') {

    $examDetailId = '';//设置为所有类型

    switch ($fieldName) {
        case 'score':
            $cacheKey = 'func:getEvaluateRank:'.$examDetailId;
            break;
        case 'question_count':
            $cacheKey = 'func:getQuestionCountRank:'.$examDetailId;
            break;
        case 'accuracy':
            $userValue = round($userValue, 4);
            $cacheKey  = 'func:getAccuracyRank:'.$examDetailId;
            break;
        case 'y_question_count':

            $yesterdayDate  = date('Ymd',strtotime("-1 day"));
            $cacheKeyUser   = 'func:getYesterdayQuestionCountByUser:' . $examDetailId.'_'.$userId;
            $cacheKeyRank   = 'func:getYesterdayQuestionCountRank:'.$examDetailId;

            //个人昨日总数
            $questionCountByUser = VipUtils::getUserDataGlobal($cacheKeyUser);
            if (!isset($questionCountByUser[$yesterdayDate]) || $questionCountByUser[$yesterdayDate] == null) {
                return 0;
            }
            $userValue = $questionCountByUser[$yesterdayDate];

            //昨日排名
            $questionCountRank = VipUtils::getUserDataGlobal($cacheKeyRank);

            if (!isset($questionCountRank[$yesterdayDate]) || $questionCountRank[$yesterdayDate] == null) {
                return 0;
            }
            $rank = $questionCountRank[$yesterdayDate];

            return getCurrentPosition($rank,$userValue);

            break;
        default:
            return 0;
    }

    if (($rank = cacheGet($cacheKey)) == null) {

        //获取该考试项目下所有用户的估分\总题数\正确率
        $rank = setDefaultUserDataRank($fieldName);

        cacheAdd($cacheKey, $rank, 30*24*60*60);
    }

    return getCurrentPosition($rank,$userValue);
}

/**
 * 获取排名信息--cache不存在的情况下,查询数据库
 *
 * @param $fieldName
 * @return array
 */
function setDefaultUserDataRank($fieldName) {
    global $cmsdb;

    $rank = [];
    switch ($fieldName) {
        case 'score':
        case 'question_count':

            $sql  = "select `{$fieldName}`,count(*) as c from `qb_user_data` group by `{$fieldName}`";
            $data = $cmsdb->getResults($sql);

            foreach ($data as $k => $v) {
                $rank[$v->{$fieldName}] = $v->c;
            }
            break;
        case 'accuracy':

            $sql            = "select count(`accuracy`) as c from `qb_user_data` where `accuracy` = 0";
            $invalidCount   = $cmsdb->getVar($sql);

            $rank    = getBatchQuery();
            $rank[0] = $invalidCount;

            break;
        default:

    }
    return $rank;
}

/**
 * 分批次查询正确率
 *
 * @param array $rank
 * @param int $offset
 * @param int $limit
 * @return array
 */
function getBatchQuery($rank = array(), $offset = 0, $limit = 30000){
    global $cmsdb;

    $sql  = "select `accuracy` from `qb_user_data` where `accuracy` > 0 limit {$offset},{$limit}";
    $data = $cmsdb->getCol($sql);

    if (!empty($data)) {

        foreach ($data as $k => $v) {
            $val = round($v, 4);
            if (isset($rank["$val"])) {
                $rank["$val"]++;
            } else {
                $rank["$val"] = 1;
            }
        }
        return getBatchQuery($rank, $limit + 1, $limit + 30000);
    }
    return $rank;
}

/**
 * 计算超越了多少人的百分比  估分\总题数\正确率的人数\昨日做题数
 *
 * @param $rank
 * @param $userValue
 * @return float
 */
function getCurrentPosition($rank,$userValue) {

    $total = $higher = 0;
    foreach ($rank as $key => $persons) {
        $total += $persons;
        if ($key > $userValue) {
            $higher += $persons;
        }
    }

    //计算排在前百分之多少
    $result = $higher/$total;
    if ($result < 0.01)
        $result = 0.01;
    return round((1 - $result),2) * 100;
}

/**
 *更新qb_user_data
 *
 * @param $queryArgs
 * @return bool
 */
function updateUserData($queryArgs) {
    global $cmsdb;

    $questions  =   json_decode($queryArgs['answer_content']);
    $duration   =   $queryArgs['duration'];
    $userId     =   $queryArgs['user_id'];

    //按知识点统计答题情况
    $changedNotes   = array();
    $totalRight     = 0;
    $totalCount     = 0;
    $statisticsTotalCount = 0;

    $qIds = array();
    foreach ($questions as $q) {
        $qIds[] = $q->id;
    }
    $notes = getNotesByQuestions($qIds);

    foreach ($questions as $q) {
        // 多知识点
        foreach ($notes[$q->id]['id'] as $noteId) {
            if (!isset($changedNotes[$noteId])) {
                $changedNotes[$noteId] = array(
                    'total' => 0,
                    'right' => 0
                );
            }

            $changedNotes[$noteId]['total']++;
            if ($q->is_right) $changedNotes[$noteId]['right']++;
        }

        //答案为空时不计入答题总数
        if(!empty($q->answer)) $statisticsTotalCount++;

        $totalCount++;
        if ($q->is_right) $totalRight++;
    }

    $userData = getUserData($userId);
    $noteInfo = normalizeUserNoteInfo($userData->note_info);

    calNoteLevel($noteInfo, $changedNotes, $userData->exam_detail_id); //能力产生变化的知识点


    $newScore = calEvaluationScore($noteInfo, $userData->exam_detail_id); //预估分

    $today          = date('Y-m-d');
    $structureKeys  = array('total_time', 'history_score', 'right_count');
    $summary        = transformDataStructure(unserialize($userData->summary_info), $structureKeys);

    $summary['right_count']             += $totalRight; //正确的题数
    $summary['total_time']              += $duration; //做题总时长
    $summary['history_score'][$today]   = intval($newScore); //历史估分

    if (count($summary['history_score']) > 7) //只记录7天
        array_shift($summary['history_score']);

    $totalCount             += $userData->question_count; //总题数
    $accuracy               = $summary['right_count']/$totalCount; //总正确率
    $statisticsTotalCount   += $userData->question_count;//统计总题数

    //更新排名缓存

    updateUserDataRank($userData->exam_detail_id, 'score', $newScore, $userData->score);

    updateUserDataRank($userData->exam_detail_id, 'question_count', $statisticsTotalCount, $userData->question_count);

    updateUserDataRank($userData->exam_detail_id, 'accuracy', $accuracy, $userData->accuracy);

    updateUserDataRank($userData->exam_detail_id, 'y_question_count', $statisticsTotalCount, $userData->question_count,$userId);

    $updatedUserData = array(
        'note_info'     => json_encode($noteInfo),
        'score'         => $newScore,
        'summary_info'  => serialize(array_values($summary)),
        'accuracy'      => $accuracy,
        'question_count' => $statisticsTotalCount
    );

    $cmsdb->update('qb_user_data', $updatedUserData, array('user_id' => $userId));


    /**-------------------------------------------------------------
     * 更新该用户的统计数据的缓存
     */
    $userData->note_info    = $updatedUserData['note_info'];
    $userData->score        = $updatedUserData['score'];
    $userData->summary_info = $updatedUserData['summary_info'];
    $userData->accuracy     = $updatedUserData['accuracy'];
    $userData->question_count = $updatedUserData['question_count'];

    $cacheKey = $cacheKey = 'qb_userData:'.$userId;
    cacheSet($cacheKey, $userData, 24*60*60);

    unset($updatedUserData);

    return true;
}


/**
 * 根据知识点学习情况计算能力评估分
 * @param array $noteInfoArray 知识点信息数组
 * @param int $examId 考试项目ID
 * @return float 最终估分
 */
function calEvaluationScore(&$noteInfoArray, $examId = 0) {
    global $cmsdb;

    if (!is_array($noteInfoArray) || empty($noteInfoArray) || $examId==0)
        return 0.0;

    /* 2015-10-27 特殊考试项目均采用国考的知识点体系 */
    if (in_array(intval($examId), array(115, 889, 1087, 1177, 902), true)) {
        $examId = 1126;
    }

    $testareaId = $cmsdb->getVar('SELECT exam_id FROM data_exam_detail WHERE id='.$examId);
    if (empty($testareaId)) return 0.0;

    $results = getNotesByTestId($testareaId);
    if (empty($results)) return 0.0;

    $notes = array();
    foreach ($results as $rs) {
        $notes[$rs->note_id]['rate'] = $rs->rate;
    }

    $sum = 0.0;
    //数据库存储结构转换为可读的结构字段列表
    $structureKeys = array('value', 'rightCount', 'totalCount', 'level', 'recomend');

    foreach ($noteInfoArray as $key => $noteInfo) {
        if (!isset($notes[$key])) continue;

        //数据库存储结构转换为可读的结构
        $noteInfo = transformDataStructure($noteInfo, $structureKeys);
        $totalNum = $noteInfo['totalCount'];
        $rightNum = $noteInfo['rightCount'];
        //如果该知识点下的做题数量不足10道,补充到10,并且按照25%的正确率补充题目
        if ($totalNum < 10) {
            $totalNum = 10;
            $rightNum += round($totalNum * 0.25 - $noteInfo['totalCount'] * 0.25);
        }
        $sum += $notes[$key]['rate'] * $noteInfo['value'] * ($rightNum / $totalNum);
    }

    return round($sum);
}

/**
 * 知识点掌握水平变化计算
 *
 * @param array $noteInfoArray 知识点信息数组（传引用）
 * @param array $changedNoteArray 做题遇到的知识点信息
 * @param int $examDetailId exam_detail_id
 * @return array 能力有变化的知识点数组
 */
function calNoteLevel(&$noteInfoArray, $changedNoteArray, $examDetailId) {

    if (!is_array($noteInfoArray) || empty($noteInfoArray) || !is_array($noteInfoArray)
        || empty($noteInfoArray))
        return array();

    $noteChanged    = array();
    $notesAccuracy  = array();

    //新版知识点结构
    $noteHierarchy = getNewNoteHierarchy();

    $examId = getExamByExamDetail($examDetailId);
    if ($examId && $results = getNotesByTestId($examId)) {
        foreach ($results as $rs) $notesAccuracy[$rs->note_id] = $rs->target_accuracy;
    }

    $UserNoteIds = array_keys($noteInfoArray);

    //数据库存储结构转换为可读的结构字段列表
    $structureKeys = array('value', 'rightCount', 'totalCount', 'level', 'recomend');

    foreach ($changedNoteArray as $noteId => $note) {
        if (!in_array($noteId, $UserNoteIds)) //做题的知识点不在用户所选考试项目的知识点内
            continue;

        //获取知识点名称
        if (isset($noteHierarchy[$noteId]))
            $noteName = strval($noteHierarchy[$noteId]['name']);
        else
            $noteName = '';

        //数据库存储结构转换为可读的结构
        $noteInfoArray[$noteId] = transformDataStructure($noteInfoArray[$noteId], $structureKeys);

        $noteInfoArray[$noteId]['totalCount'] += $note['total'];
        $noteInfoArray[$noteId]['rightCount'] += $note['right'];

        if ($noteInfoArray[$noteId]['level'] == 0) { //该知识点第一次遇到
            $noteChanged[] = array(
                'id' => $noteId,
                'name' => $noteName,
                'from' => 0, //初始为0
                'to' => ++$noteInfoArray[$noteId]['level']
            );

        } elseif ($noteInfoArray[$noteId]['totalCount'] < 30) { //该知识点已经做过且做题数小于30
            $noteInfoArray[$noteId]['level'] = 1;

        } elseif ($noteInfoArray[$noteId]['totalCount'] >= 30) { //该知识点做题数不小于30

            if (isset($notesAccuracy[$noteId])) {
                $targetAccuracy = $notesAccuracy[$noteId];
            } else {
                $targetAccuracy = 1;
            }

            //2016-04-20 新的知识点正确率逻辑
            if ($note['total'] < 30) {
                $currAccuracy = ($note['right'] + (30 - $note['total']) * $noteInfoArray[$noteId]['level'] * $targetAccuracy / 5) / 30;
            } else {
                $currAccuracy = $note['right'] / $note['total'];
            }

            if ($currAccuracy < $targetAccuracy) { //未达到目标正确率
                $currLevel = round(4*($currAccuracy-$targetAccuracy)/$targetAccuracy) + 5;

                if ($currLevel > $noteInfoArray[$noteId]['level']
                    && $noteInfoArray[$noteId]['level'] < 5) { //当前计算的level大于之前的level并且之前的level小于5
                    $noteChanged[] = array(
                        'id'    => $noteId,
                        'name'  => $noteName,
                        'from'  => $noteInfoArray[$noteId]['level'],
                        'to'    => ++$noteInfoArray[$noteId]['level']
                    );

                } elseif ($currLevel < $noteInfoArray[$noteId]['level']
                    && $noteInfoArray[$noteId]['level'] > 1) { //当前计算的level小于之前的level且之前的level大于1
                    $noteChanged[] = array(
                        'id'    => $noteId,
                        'name'  => $noteName,
                        'from'  => $noteInfoArray[$noteId]['level'],
                        'to'    => --$noteInfoArray[$noteId]['level']
                    );
                }

            } elseif ($noteInfoArray[$noteId]['level'] < 5) { //达到目标正确率且之前的level小于5
                $noteChanged[] = array(
                    'id'    => $noteId,
                    'name'  => $noteName,
                    'from'  => $noteInfoArray[$noteId]['level'],
                    'to'    => ++$noteInfoArray[$noteId]['level']
                );
            }
        }

        //还原存储结构(去除显式key)
        $noteInfoArray[$noteId] = array_values($noteInfoArray[$noteId]);
    }

    return $noteChanged;
}